package cn.ilikes.tools.nosql.jpa.query.pasers;

import net.sf.jsqlparser.expression.BinaryExpression;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue;
import net.sf.jsqlparser.expression.NullValue;
import net.sf.jsqlparser.expression.Parenthesis;
import net.sf.jsqlparser.expression.StringValue;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
import net.sf.jsqlparser.expression.operators.relational.Between;
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.expression.operators.relational.GreaterThan;
import net.sf.jsqlparser.expression.operators.relational.GreaterThanEquals;
import net.sf.jsqlparser.expression.operators.relational.InExpression;
import net.sf.jsqlparser.expression.operators.relational.LikeExpression;
import net.sf.jsqlparser.expression.operators.relational.MinorThan;
import net.sf.jsqlparser.expression.operators.relational.MinorThanEquals;
import net.sf.jsqlparser.expression.operators.relational.NotEqualsTo;
import net.sf.jsqlparser.schema.Column;

import org.slf4j.Logger;

import cn.ilikes.tools.logs.Loggerfactory;
import cn.ilikes.tools.nosql.jpa.query.iquerys.IQuery;
import cn.ilikes.tools.nosql.jpa.query.sql.element.Properties;
import cn.ilikes.tools.nosql.jpa.query.sql.element.SQLTable;
import cn.ilikes.tools.nosql.jpa.query.sql.element.WhereList;
import cn.ilikes.tools.nosql.jpa.query.sql.element.WhereList.ListType;

public class PaserWhere {

	private static Logger logger = Loggerfactory.instance(PaserWhere.class);

	/***
	 * 
	 * @param parentWhere
	 * @param childWhere
	 * @param table
	 * @param whereList
	 * @param position
	 *                  -1 left 0 中间 1 right
	 * @param child
	 */

	public void paserWhere(Expression parentWhere, SQLTable table, boolean child) {
		WhereList root = new WhereList();
		table.setWhereList(root);
		if (parentWhere instanceof Parenthesis) {
			Parenthesis parenthesis = (Parenthesis) parentWhere;
			parentWhere = parenthesis.getExpression();
		}
		paserWhere(parentWhere, null, table, root, 0, child);
	}

	public void paserBetween(SQLTable table, Expression paser, WhereList whereList) {

		Between between = (Between) paser;
		whereList.setListType(ListType.between);
		Column column = (Column) between.getLeftExpression();
		Properties properties = new Properties(Properties.Type.property, String.class, column.getWholeColumnName());
		whereList.setLeftList(properties);
		Properties rightColumnProperties = new Properties(Properties.Type.value);
		Properties.Between betweenProperties = rightColumnProperties.new Between();
		rightColumnProperties.setValueType(betweenProperties.getClass());
		rightColumnProperties.setValue(betweenProperties);
		whereList.setRightList(rightColumnProperties);
		Expression start = between.getBetweenExpressionStart();
		if (start instanceof StringValue) {
			start = (StringValue) start;
			betweenProperties.setStart(((StringValue) start).getValue());

		} else if (start instanceof LongValue) {
			start = (LongValue) start;
			betweenProperties.setStart(((LongValue) start).getValue());
		}

		Expression end = between.getBetweenExpressionEnd();

		if (end instanceof StringValue) {
			end = (StringValue) end;
			betweenProperties.setEnd(((StringValue) end).getValue());

		} else if (end instanceof LongValue) {
			start = (LongValue) end;
			betweenProperties.setEnd(((LongValue) end).getValue());
		}

	}

	private void paserWhere(Expression parentWhere, Expression childWhere, SQLTable table, WhereList whereList, int position, boolean child) {
		if (child && childWhere instanceof Parenthesis) {
			Parenthesis parenthesis = (Parenthesis) childWhere;
			Expression x = parenthesis.getExpression();

			paserWhere(childWhere, x, table, whereList, position, true);
		} else {

			Expression paser = (!child ? parentWhere : childWhere);
			{

				if (paser instanceof Between) {
					paserBetween(table, paser, whereList);
				} else if (paser instanceof InExpression) {
					InExpression bin = (InExpression) paser;
					whereList.setListType(ListType.in);
					paserInExpression(table, whereList, bin);
				} else if (paser instanceof OrExpression || paser instanceof AndExpression || paser instanceof EqualsTo || paser instanceof LikeExpression
						|| paser instanceof GreaterThan || paser instanceof GreaterThanEquals || paser instanceof MinorThan || paser instanceof MinorThanEquals
						|| paser instanceof NotEqualsTo) {

					if (paser instanceof NotEqualsTo)
						whereList.setListType(ListType.no_equals);
					if (paser instanceof OrExpression)
						whereList.setListType(ListType.or);
					if (paser instanceof AndExpression)
						whereList.setListType(ListType.and);
					if (paser instanceof EqualsTo)
						whereList.setListType(ListType.equals);
					if (paser instanceof LikeExpression)
						whereList.setListType(ListType.like);
					if (paser instanceof GreaterThan)
						whereList.setListType(ListType.greaterThan);
					if (paser instanceof GreaterThanEquals)
						whereList.setListType(ListType.greaterThanEquals);
					if (paser instanceof MinorThan)
						whereList.setListType(ListType.minorThan);
					if (paser instanceof MinorThanEquals)
						whereList.setListType(ListType.minorThanEquals);

					{
						BinaryExpression bin = (BinaryExpression) paser;
						{
							paserBinaryExpression(table, whereList, bin);
						}
					}
				}
			}//end

		}

	}

	private void paserInExpression(SQLTable table, WhereList whereList, InExpression bin) {
		{//left  end
			Expression left = bin.getLeftExpression();

			if (left instanceof Column) {
				Column column = (Column) left;
				Properties properties = new Properties(Properties.Type.property, String.class, column.getWholeColumnName());
				whereList.setLeftList(properties);
			} else {
				if (!(left instanceof Parenthesis)) {
					WhereList leftWhereList = new WhereList();
					whereList.setLeftList(leftWhereList);
					paserWhere(bin, left, table, leftWhereList, -1, true);
				} else {
					ParentWhereList parent = new ParentWhereList();
					whereList.setLeftList(parent);
					paserWhere(bin, left, table, parent, -1, true);
				}

			}
		}
		{// right end 
			ExpressionList right = (ExpressionList) bin.getItemsList();

			String value = "";
			for (Object o_ : right.getExpressions()) {
				value = value + o_;
			}
			Properties properties = new Properties(Properties.Type.value, String.class, value);
			whereList.setRightList(properties);

		}

	}

	private void paserBinaryExpression(SQLTable table, WhereList whereList, BinaryExpression bin) {
		{//left  end
			Expression left = bin.getLeftExpression();

			if (left instanceof Column) {
				Column column = (Column) left;
				Properties properties = new Properties(Properties.Type.property, String.class, column.getWholeColumnName());
				whereList.setLeftList(properties);
			} else {
				if (!(left instanceof Parenthesis)) {
					WhereList leftWhereList = new WhereList();
					whereList.setLeftList(leftWhereList);
					paserWhere(bin, left, table, leftWhereList, -1, true);
				} else {
					ParentWhereList parent = new ParentWhereList();
					whereList.setLeftList(parent);
					paserWhere(bin, left, table, parent, -1, true);
				}

			}
		}
		{// right end 
			Expression right = bin.getRightExpression();
			if (right instanceof Column) {
				Column column = (Column) right;
				Properties properties = new Properties(Properties.Type.value, String.class, column.getWholeColumnName());
				whereList.setRightList(properties);
			} else if (right instanceof NullValue) {
				NullValue column = (NullValue) right;
				Properties properties = new Properties(Properties.Type.value, String.class, IQuery.SQL_NULL_VALUES);
				whereList.setRightList(properties);
			} else if (right instanceof StringValue) {
				StringValue column = (StringValue) right;
				Properties properties = new Properties(Properties.Type.value, String.class, column.getValue());
				whereList.setRightList(properties);
			} else if (right instanceof LongValue) {
				LongValue column = (LongValue) right;
				Properties properties = new Properties(Properties.Type.value, Long.class, Long.valueOf(column.getValue()));
				whereList.setRightList(properties);
			} else {
				if (!(right instanceof Parenthesis)) {
					WhereList leftWhereList = new WhereList();
					whereList.setRightList(leftWhereList);
					paserWhere(bin, right, table, leftWhereList, 1, true);
				} else {
					{
						ParentWhereList parent = new ParentWhereList();
						whereList.setRightList(parent);
						paserWhere(bin, right, table, parent, -1, true);
					}
				}
			}
		}
	}

}
